package com.xuanwei.core.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.xuanwei.core.entity.CourierInfo;
import com.xuanwei.core.entity.bo.CouponUseBo;
import com.xuanwei.core.entity.constant.RefundConstant;
import com.xuanwei.core.entity.param.Comment;
import com.xuanwei.core.entity.vo.*;
import com.xuanwei.core.entity.param.UserAddress;
import com.xuanwei.core.enums.CourierStatus;
import com.xuanwei.core.enums.OrderStatus;
import com.xuanwei.core.enums.RefundStatus;
import com.xuanwei.core.exception.XwException;
import com.xuanwei.core.mq.SendProduct;
import com.xuanwei.core.redisson.RedissonService;
import com.xuanwei.core.service.*;
import com.xuanwei.core.util.GenerateOrderNO;
import com.xuanwei.dao.Do.OrderDo;
import com.xuanwei.dao.entity.*;
import com.xuanwei.dao.mapper.XwOrderMapper;
import com.xuanwei.xwcommon.util.BeanUtil;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author mjy
 * @since 2019-07-11
 */
@Service
@Slf4j
public class XwOrderServiceImpl extends ServiceImpl<XwOrderMapper, XwOrder> implements IXwOrderService {

    private IXwCartService cartService;

    private IXwProductSkuService productSkuService;

    private IXwProductService productService;

    private IXwUserAddressService userAddressService;

    private IXwOrderItemService orderItemService;

    private IXwOrderStatisticsService orderStatisticsService;

    private RedissonService redissonService;

    private IXwOrderRefundService orderRefundService;

    private IXwOrderRefundRecordService orderRefundRecordService;

    private IXwUserCouponService userCouponService;

    private IXwOrderCourierService orderCourierService;

    private IXwUserService userService;

    private IXwCourierCompanyService courierCompanyService;

    private SendProduct sendProduct;

    private IXwIntegralRecordService integralRecordService;

    private IXwOrderCommentService orderCommentService;


    private IXwOrderCancelRecordService orderCancelRecordService;

    public XwOrderServiceImpl(IXwCartService cartService,
                              IXwProductSkuService productSkuService,
                              IXwProductService productService,
                              IXwUserAddressService userAddressService,
                              IXwOrderItemService orderItemService,
                              IXwOrderStatisticsService orderStatisticsService,
                              RedissonService redissonService,
                              IXwOrderRefundService orderRefundService,
                              IXwOrderRefundRecordService orderRefundRecordService,
                              IXwUserCouponService userCouponService,
                              IXwOrderCourierService orderCourierService,
                              IXwUserService userService,
                              IXwCourierCompanyService courierCompanyService,
                              SendProduct sendProduct,
                              IXwIntegralRecordService integralRecordService,
                              IXwOrderCommentService orderCommentService,
                              IXwOrderCancelRecordService orderCancelRecordService
    ) {
        this.cartService = cartService;
        this.productSkuService = productSkuService;
        this.productService = productService;
        this.userAddressService = userAddressService;
        this.orderItemService = orderItemService;
        this.orderStatisticsService = orderStatisticsService;
        this.redissonService = redissonService;
        this.orderRefundService = orderRefundService;
        this.orderRefundRecordService = orderRefundRecordService;
        this.userCouponService = userCouponService;
        this.orderCourierService = orderCourierService;
        this.userService = userService;
        this.courierCompanyService = courierCompanyService;
        this.sendProduct = sendProduct;
        this.integralRecordService = integralRecordService;
        this.orderCommentService = orderCommentService;
        this.orderCancelRecordService = orderCancelRecordService;
    }

    @Override
    public PayOrderVo getOrderData(List<Integer> ids, Integer userId, Integer couponId, Integer addressId) {
        List<XwCart> xwCarts = cartService.getBaseMapper().selectList(new QueryWrapper<XwCart>()
                .in("id", ids)
                .orderByDesc("create_time"));
        if (couponId != null) {
            CouponUseBo canUse = userCouponService.isCanUse(userId, couponId, xwCarts);
            if (!canUse.isCanUse()) {
                throw new XwException(canUse.getReason());
            }
        }
        List<CartVo> cartVos = Lists.newArrayListWithCapacity(xwCarts.size());
        xwCarts.forEach(s -> {
            CartVo cartVo = new CartVo();
            cartVo.setId(s.getId());
            cartVo.setProductId(s.getProductId());
            cartVo.setProductName(s.getProductName());
            cartVo.setSkuName(s.getProductAttributeName());
            cartVo.setCount(s.getCount());
            cartVo.setPrice(s.getPrice());
            cartVo.setImage(s.getProductImage());
            cartVos.add(cartVo);
        });


        PayOrderVo payOrderVo = new PayOrderVo();
        payOrderVo.setCartVos(cartVos);
        UserAddress userAddress = userAddressService.findById(addressId, userId);
        payOrderVo.setUserAddress(userAddress);

        XwUserCoupon userCoupon = null;
        if (couponId != null) {
            userCoupon = userCouponService.getById(couponId);
        }
        BigDecimal totalMoney = getTotalMoney(cartVos);
        payOrderVo.setTotalAmount(totalMoney);
        payOrderVo.setFreight(new BigDecimal("0.00"));
        if (userCoupon != null) {
            BigDecimal subtract = totalMoney.subtract(userCoupon.getCouponAmount());
            if (subtract.compareTo(new BigDecimal(0)) < 1) {
                subtract = new BigDecimal(0.01);
                payOrderVo.setCouponAmount(totalMoney);
            } else {
                payOrderVo.setCouponAmount(userCoupon.getCouponAmount());
            }
            payOrderVo.setActualAmount(subtract);
            payOrderVo.setIntegral(payOrderVo.getActualAmount().intValue());
            payOrderVo.setCouponName(userCoupon.getCouponTitle());

        } else {
            Integer count = userCouponService.findCountByUser(userId, xwCarts);
            payOrderVo.setCouponCount(count);
            payOrderVo.setIntegral(totalMoney.intValue());
            payOrderVo.setActualAmount(totalMoney);
            payOrderVo.setCouponAmount(new BigDecimal("0.00"));
        }
        return payOrderVo;
    }

    /**
     * 获取总金额
     *
     * @param cartVos 购物车
     * @return 总金额
     */
    private BigDecimal getTotalMoney(List<CartVo> cartVos) {
        BigDecimal total = new BigDecimal("0.00");
        for (CartVo cartVo : cartVos) {
            total = cartVo.getPrice().multiply(new BigDecimal(cartVo.getCount())).add(total);
        }
        return total;
    }

    @Override
    public PayOrderVo getOrderData(Integer skuId, Integer count, Integer userId, Integer couponId, Integer addressId) {
        XwCart cart = cartService.generateCart(skuId, count);
        CartVo cartVo = new CartVo();
        cartVo.setId(cart.getId());
        cartVo.setProductName(cart.getProductName());
        cartVo.setSkuName(cart.getProductAttributeName());
        cartVo.setCount(cart.getCount());
        cartVo.setPrice(cart.getPrice());
        cartVo.setImage(cart.getProductImage());
        List<CartVo> cartVos = Lists.newArrayListWithCapacity(1);
        cartVos.add(cartVo);
        ArrayList<XwCart> xwCarts = Lists.newArrayList(cart);
        if (couponId != null) {
            CouponUseBo canUse = userCouponService.isCanUse(userId, couponId, xwCarts);
            if (!canUse.isCanUse()) {
                throw new XwException(canUse.getReason());
            }
        }
        UserAddress userAddress = userAddressService.findById(addressId, userId);
        PayOrderVo payOrderVo = new PayOrderVo();
        payOrderVo.setCartVos(cartVos);
        payOrderVo.setUserAddress(userAddress);

        XwUserCoupon userCoupon = null;
        if (couponId != null) {
            userCoupon = userCouponService.getById(couponId);
        }
        BigDecimal totalMoney = getTotalMoney(cartVos);
        payOrderVo.setTotalAmount(totalMoney);
        payOrderVo.setFreight(new BigDecimal("0.00"));
        if (userCoupon != null) {
            BigDecimal subtract = totalMoney.subtract(userCoupon.getCouponAmount());
            if (subtract.compareTo(new BigDecimal(0)) < 1) {
                subtract = new BigDecimal(0.01);
                payOrderVo.setCouponAmount(totalMoney);
            } else {
                payOrderVo.setCouponAmount(userCoupon.getCouponAmount());
            }
            payOrderVo.setActualAmount(subtract);
            payOrderVo.setIntegral(payOrderVo.getActualAmount().intValue());
            payOrderVo.setCouponName(userCoupon.getCouponTitle());

        } else {
            Integer num = userCouponService.findCountByUser(userId, xwCarts);
            payOrderVo.setCouponCount(num);
            payOrderVo.setIntegral(totalMoney.intValue());
            payOrderVo.setActualAmount(totalMoney);
            payOrderVo.setCouponAmount(new BigDecimal("0.00"));
        }
        return payOrderVo;
    }

    @Override
    @Transactional
    public XwOrder generateOrder(List<Integer> ids, Integer addressId, String remark, Integer couponId, Integer userId) {

        List<XwCart> carts = cartService.getBaseMapper().selectBatchIds(ids);
        UserAddress userAddress = userAddressService.findById(addressId, null);
        if (userAddress == null) {
            throw new XwException("地址不存在");
        }
        XwOrder order = new XwOrder();
        order.setProvince(userAddress.getProvince());
        order.setCity(userAddress.getCity());
        order.setArea(userAddress.getArea());
        order.setAddress(userAddress.getReceiveAddress());
        order.setReceiveName(userAddress.getReceiveName());
        order.setReceivePhone(userAddress.getReceivePhone());

        //商品总价格
        BigDecimal total = new BigDecimal(0);
        for (XwCart cart : carts) {
            total = total.add(cart.getPrice().multiply(new BigDecimal(cart.getCount())));
        }
        order.setTotalAmount(total);
        //TODO   运费设置为0
        order.setFreight(new BigDecimal(0));
        CouponUseBo canUse = null;
        XwUserCoupon coupon = null;
        if (couponId != null) {
            canUse = userCouponService.isCanUse(userId, couponId, carts);
            if (!canUse.isCanUse()) {
                log.warn("{}不可用", couponId);
                throw new XwException(canUse.getReason());
            }
            coupon = userCouponService.getById(couponId);
            order.setPreferentialAmount(coupon.getCouponAmount());
        } else {
            order.setPreferentialAmount(new BigDecimal(0));
        }
        //实际金额
        BigDecimal s = order.getTotalAmount().add(order.getFreight()).subtract(order.getPreferentialAmount());
        if (s.compareTo(new BigDecimal(0)) > 0) {
            order.setActualAmount(s);
        } else {
            order.setActualAmount(new BigDecimal(0.01));
            order.setPreferentialAmount(order.getTotalAmount());
        }

        order.setRemark(remark);
        order.setStatus(OrderStatus.PAY_NO.getCode());
        order.setOrderNo(GenerateOrderNO.makeOrderNum());
        order.setCreateTime(LocalDateTime.now());
        order.setUpdateTime(LocalDateTime.now());
        order.setUserId(userId);
        save(order);

        Integer orderId = order.getId();

        //消费优惠券
        if (couponId != null) {
            userCouponService.consume(userId, couponId, orderId);
        }

        List<XwOrderItem> orderItems = Lists.newArrayListWithCapacity(carts.size());

        Integer totalCount = 0;
        for (XwCart cart : carts) {
            XwOrderItem orderItem = new XwOrderItem();
            Integer skuId = cart.getSkuId();
            //乐观锁住库存
            XwProductSku productSku = productSkuService.getOne(new QueryWrapper<XwProductSku>()
                    .select("id,stock,`version`")
                    .eq("id", skuId));
            Integer stock = productSku.getStock();
            if (cart.getCount() > stock) {
                throw new XwException("商品库存不足");
            }
            //减去sku的库存
            productSku.setStock(stock - cart.getCount());
            productSku.setUpdateTime(LocalDateTime.now());
            productSkuService.getBaseMapper().updateById(productSku);
            //总数量
            totalCount += cart.getCount();
            //订单明细
            orderItem.setOrderId(orderId);
            orderItem.setCount(cart.getCount());
            orderItem.setPrice(cart.getPrice());
            orderItem.setProductId(cart.getProductId());
            orderItem.setProductName(cart.getProductName());
            orderItem.setSkuId(cart.getSkuId());
            orderItem.setImage(cart.getProductImage());
            orderItem.setSkuName(cart.getProductAttributeName());
            orderItem.setTotalAmount(cart.getPrice().multiply(new BigDecimal(cart.getCount())));
            orderItem.setActualAmount(orderItem.getTotalAmount());
            if (canUse != null && canUse.getProductId() != null && canUse.getProductId().equals(cart.getProductId())) {
                orderItem.setPreferentialAmount(coupon.getCouponAmount());
                XwProduct product = productService.getOne(new QueryWrapper<XwProduct>()
                        .select("id,min_price")
                        .eq("id", cart.getProductId()));
                if (product.getMinPrice().subtract(orderItem.getPreferentialAmount()).compareTo(new BigDecimal(0)) < 1) {
                    orderItem.setPreferentialAmount(product.getMinPrice());
                }
                orderItem.setActualAmount(orderItem.getTotalAmount().subtract(orderItem.getPreferentialAmount()));
            }
            orderItems.add(orderItem);

            //减去商品的库存
            XwProduct product = productService.getOne(new QueryWrapper<XwProduct>()
                    .select("id,stock,`version`")
                    .eq("id", carts.get(0).getProductId()));
            product.setStock(product.getStock() - totalCount);
            product.setUpdateTime(LocalDateTime.now());
            productService.getBaseMapper().updateById(product);
            sendProduct.update(product.getId());
        }

        //保存订单明细
        orderItemService.saveBatch(orderItems);
        //删除购物车
        cartService.getBaseMapper().deleteBatchIds(ids);

        String body = orderItems.get(0).getProductName().substring(0, 5) + "等" + totalCount + "件商品";
        order.setPayBody(body);
        return order;
    }

    @Override
    @Transactional
    public XwOrder generateOrder(Integer skuId, Integer count, Integer addressId, String remark, Integer couponId, Integer userId) {

        XwProductSku productSku = productSkuService.getOne(new QueryWrapper<XwProductSku>()
                .select("id,stock,price,product_id,attribute_ids,`version`")
                .eq("id", skuId));
        if (productSku == null) {
            throw new XwException("商品不存在");
        }
        if (productSku.getStock() < count) {
            throw new XwException("商品库存不足");
        }
        UserAddress userAddress = userAddressService.findById(addressId, null);
        if (userAddress == null) {
            throw new XwException("地址不存在");
        }
        XwOrder order = new XwOrder();
        order.setProvince(userAddress.getProvince());
        order.setCity(userAddress.getCity());
        order.setArea(userAddress.getArea());
        order.setAddress(userAddress.getReceiveAddress());
        order.setReceiveName(userAddress.getReceiveName());
        order.setReceivePhone(userAddress.getReceivePhone());

        //商品总价格
        BigDecimal total = productSku.getPrice().multiply(new BigDecimal(count));

        order.setTotalAmount(total);
        //TODO   运费设置为0
        order.setFreight(new BigDecimal(0));
        CouponUseBo couponUseBo = null;
        XwUserCoupon coupon = null;
        if (couponId != null) {
            XwCart cart = cartService.generateCart(skuId, count);
            couponUseBo = userCouponService.isCanUse(userId, couponId, Lists.newArrayList(cart));
            if (!couponUseBo.isCanUse()) {
                log.warn("couponId={} 不可用", couponId);
                throw new XwException("该优惠券不可用");
            }
            coupon = userCouponService.getById(couponId);
            order.setPreferentialAmount(coupon.getCouponAmount());
        } else {
            order.setPreferentialAmount(order.getTotalAmount());
            order.setPreferentialAmount(new BigDecimal(0));
        }

        //实际金额
        BigDecimal s = order.getTotalAmount().add(order.getFreight()).subtract(order.getPreferentialAmount());
        if (s.compareTo(new BigDecimal(0)) == 1) {
            order.setActualAmount(s);
        } else {
            order.setActualAmount(new BigDecimal(0));
        }
        order.setRemark(remark);
        order.setStatus(OrderStatus.PAY_NO.getCode());
        order.setOrderNo(GenerateOrderNO.makeOrderNum());
        order.setCreateTime(LocalDateTime.now());
        order.setUpdateTime(LocalDateTime.now());
        order.setUserId(userId);
        save(order);

        Integer orderId = order.getId();
        //消费优惠券
        if (couponId != null) {
            userCouponService.consume(userId, couponId, orderId);
        }
        //减去sku的库存
        productSku.setStock(productSku.getStock() - count);
        productSku.setUpdateTime(LocalDateTime.now());
        productSkuService.getBaseMapper().updateById(productSku);
        //减去商品的库存
        XwProduct product = productService.getOne(new QueryWrapper<XwProduct>()
                .select("id,stock,`name`,`version`,min_price")
                .eq("id", productSku.getProductId()));
        product.setStock(product.getStock() - count);
        product.setUpdateTime(LocalDateTime.now());
        productService.getBaseMapper().updateById(product);
        sendProduct.update(product.getId());
        //保存订单详情
        XwOrderItem orderItem = new XwOrderItem();
        orderItem.setOrderId(orderId);
        orderItem.setCount(count);
        orderItem.setPrice(productSku.getPrice());
        orderItem.setProductId(productSku.getProductId());
        orderItem.setProductName(product.getName());
        orderItem.setSkuId(skuId);
        XwCart cart = cartService.generateCart(skuId, count);
        orderItem.setImage(cart.getProductImage());
        orderItem.setSkuName(cart.getProductAttributeName());
        orderItem.setTotalAmount(cart.getPrice().multiply(new BigDecimal(cart.getCount())));
        orderItem.setActualAmount(orderItem.getTotalAmount());
        if (couponUseBo != null && couponUseBo.getProductId() != null) {
            orderItem.setPreferentialAmount(coupon.getCouponAmount());
            if (product.getMinPrice().subtract(orderItem.getPreferentialAmount()).compareTo(new BigDecimal(0)) < 1) {
                orderItem.setPreferentialAmount(product.getMinPrice());
            }
            orderItem.setActualAmount(orderItem.getTotalAmount().subtract(orderItem.getPreferentialAmount()));
        }
        orderItemService.save(orderItem);
        String body = orderItem.getProductName().substring(0, 5) + "等" + count + "件商品";
        order.setPayBody(body);
        return order;
    }

    @Override
    @Transactional
    public void orderSuccess(String orderNo) {
        XwOrder order = baseMapper.selectOne(new QueryWrapper<XwOrder>()
                .select("id,actual_amount")
                .eq("order_no", orderNo)
                .in("`status`", OrderStatus.PAY_NO.getCode(), OrderStatus.NO.getCode()));
        if (order == null) {
            log.error("{} is not exist", orderNo);
            throw new XwException();
        }
        //修改订单状态
        order.setStatus(OrderStatus.PAY_SUCCESS.getCode());
        order.setPayTime(LocalDateTime.now());
        updateById(order);
        //统计表
        LocalDateTime now = LocalDateTime.now();
        int year = now.getYear();
        int monthValue = now.getMonthValue();
        RLock lock = redissonService.getRLock("orderStatistics" + year + monthValue);
        try {
            boolean b = lock.tryLock(1, TimeUnit.SECONDS);
            if (b) {
                //该处不能用悲观锁,在没有数据的时候是不能锁住该条数据
                XwOrderStatistics orderStatistics = orderStatisticsService.getBaseMapper()
                        .selectOne(new QueryWrapper<XwOrderStatistics>()
                                .select("id,amount,refund,order_count")
                                .eq("statistics_year", year)
                                .eq("statistics_month", monthValue));
                if (orderStatistics == null) {
                    orderStatistics = new XwOrderStatistics();
                    orderStatistics.setOrderCount(1);
                    orderStatistics.setAmount(order.getActualAmount());
                    orderStatistics.setStatisticsMonth(monthValue);
                    orderStatistics.setStatisticsYear(year);
                    orderStatistics.setUpdateTime(LocalDateTime.now());
                    orderStatistics.setCreateTime(LocalDateTime.now());
                    orderStatisticsService.save(orderStatistics);
                } else {
                    orderStatistics.setUpdateTime(LocalDateTime.now());
                    orderStatistics.setOrderCount(orderStatistics.getOrderCount() + 1);
                    orderStatistics.setAmount(orderStatistics.getAmount().add(order.getActualAmount()));
                    orderStatisticsService.updateById(orderStatistics);
                }
            }
            lock.unlock();
        } catch (Exception e) {
            e.printStackTrace();
            lock.unlock();
        }
    }

    @Override
    @Transactional
    public void orderRefundSuccess(String orderNo) {
        XwOrder order = baseMapper.selectOne(new QueryWrapper<XwOrder>()
                .select("id,actual_amount")
                .eq("order_no", orderNo)
                .eq("`status`", OrderStatus.AFTER_SALE.getCode()));
        if (order == null) {
            log.error("{} is not exist", orderNo);
            throw new XwException();
        }

        XwOrderRefund orderRefund = orderRefundService.getBaseMapper().selectOne(new QueryWrapper<XwOrderRefund>()
                .select("id").eq("order_id", order.getId())
                .eq("`status`", RefundStatus.REFUNDING.getCode()));

        if (orderRefund == null) {
            log.error("refund is not exist ");
            throw new XwException();
        }
        //修改退款成功
        orderRefund.setStatus(RefundStatus.REFUND_SUCCESS.getCode());
        orderRefundService.getBaseMapper().updateById(orderRefund);

        //添加退款记录
        orderRefundRecordService.save(orderRefund.getId(), RefundConstant.SUCCESS);

        LocalDateTime now = LocalDateTime.now();
        int year = now.getYear();
        int monthValue = now.getMonthValue();
        //修改统计表
        RLock lock = redissonService.getRLock("orderStatistics" + year + monthValue);
        try {
            boolean b = lock.tryLock(1, TimeUnit.SECONDS);
            if (b) {
                //该处不能用悲观锁,在没有数据的时候是不能锁住该条数据
                XwOrderStatistics orderStatistics = orderStatisticsService.getBaseMapper()
                        .selectOne(new QueryWrapper<XwOrderStatistics>()
                                .select("id,amount,refund,order_count")
                                .eq("statistics_year", year)
                                .eq("statistics_month", monthValue));
                if (orderStatistics == null) {
                    orderStatistics = new XwOrderStatistics();
                    orderStatistics.setRefund(order.getActualAmount());
                    orderStatistics.setStatisticsMonth(monthValue);
                    orderStatistics.setStatisticsYear(year);
                    orderStatistics.setUpdateTime(LocalDateTime.now());
                    orderStatistics.setCreateTime(LocalDateTime.now());
                    orderStatisticsService.save(orderStatistics);
                } else {
                    orderStatistics.setUpdateTime(LocalDateTime.now());
                    orderStatistics.setOrderCount(orderStatistics.getOrderCount() - 1);
                    orderStatistics.setAmount(orderStatistics.getAmount().subtract(order.getActualAmount()));
                    orderStatisticsService.updateById(orderStatistics);
                }
            }
            lock.unlock();
        } catch (Exception e) {
            e.printStackTrace();
            lock.unlock();
        }
        //修改商品库存
        updateStock(order.getId());

    }

    /**
     * 修改库存
     *
     * @param orderId 订单ID
     */
    private void updateStock(Integer orderId) {
        List<XwOrderItem> orderItems = orderItemService.list(new QueryWrapper<XwOrderItem>()
                .select("id,product_id,sku_id,`count`")
                .eq("order_id", orderId));

        orderItems.forEach(s -> {
            Integer productId = s.getProductId();
            Integer skuId = s.getSkuId();
            XwProductSku productSku = productSkuService.getBaseMapper().selectOne(new QueryWrapper<XwProductSku>()
                    .select("id,stock")
                    .eq("id", skuId));
            productSku.setStock(productSku.getStock() + s.getCount());
            productSku.setUpdateTime(LocalDateTime.now());
            productSkuService.updateById(productSku);

            XwProduct product = productService.getBaseMapper().selectOne(new QueryWrapper<XwProduct>()
                    .select("id,stock")
                    .eq("id", productId));
            product.setStock(product.getStock() + s.getCount());
            product.setUpdateTime(LocalDateTime.now());
            productService.updateById(product);
            sendProduct.update(product.getId());
        });

    }

    @Override
    @Transactional
    public void orderClose(Integer orderId, String reason) {

        // 修改订单状态
        XwOrder order = baseMapper.selectOne(new QueryWrapper<XwOrder>()
                .select("id")
                .eq("id", orderId)
                .in("`status`", OrderStatus.PAY_NO.getCode(), OrderStatus.NO.getCode()));

        if (order == null) {
            throw new XwException("数据不存在");
        }
        order.setStatus(OrderStatus.CLOSE.getCode());
        order.setCloseTime(LocalDateTime.now());
        updateById(order);

        XwOrderCancelRecord orderCancelRecord = new XwOrderCancelRecord();
        orderCancelRecord.setOrderId(orderId);
        orderCancelRecord.setCancelReason(reason);
        orderCancelRecord.setCancelTime(LocalDateTime.now());
        orderCancelRecordService.save(orderCancelRecord);
        // 返回库存
        updateStock(order.getId());

    }

    @Override
    public void orderDelete(Integer orderId) {

        //只有关闭的订单和完成的订单,退款成功才能删除
        XwOrder order = baseMapper.selectOne(new QueryWrapper<XwOrder>()
                .select("id,`status`")
                .eq("id", orderId));
        if (order == null) {
            throw new XwException("订单不存在");
        }
        if (!Arrays.asList(OrderStatus.CLOSE.getCode(),
                OrderStatus.AFTER_SALE.getCode(),
                OrderStatus.SUCCESS.getCode()).contains(order.getStatus())) {
            throw new XwException("订单不能删除");
        }
        if (order.getStatus().equals(OrderStatus.AFTER_SALE.getCode())) {
            XwOrderRefund orderRefund = orderRefundService.getOne(
                    new QueryWrapper<XwOrderRefund>()
                            .select("id,`status`")
                            .eq("order_id", orderId));
            if (!orderRefund.getStatus().equals(RefundStatus.REFUND_SUCCESS.getCode())) {
                throw new XwException("该订单不能删除");
            }
        }
        order.setUserDeleteFlag(1);
        updateById(order);
    }

    @Override
    public List<OrderVo> findUserOrder(Integer userId, Integer type, Page<XwOrder> page) {
        QueryWrapper<XwOrder> wrapper = new QueryWrapper<>();
        wrapper.select("id,order_no,actual_amount,`status`");
        if (type != null) {
            if (type == 0) {
                wrapper.in("`status`", OrderStatus.PAY_NO.getCode(), OrderStatus.NO.getCode());
            } else {
                wrapper.eq("`status`", type);
            }
        } else {
            wrapper.ne("`status`", OrderStatus.AFTER_SALE.getCode());
        }
        wrapper.eq("user_id", userId)
                .eq("user_delete_flag", 0);
        wrapper.orderByDesc("create_time");
        baseMapper.selectPage(page, wrapper);
        List<OrderVo> orderVos = BeanUtil.copyList(page.getRecords(), OrderVo.class);
        if (orderVos != null) {
            orderVos.forEach(i -> {
                Integer id = i.getId();
                List<XwOrderItem> orderItems = orderItemService.list(new QueryWrapper<XwOrderItem>()
                        .select("id,product_name,`count`,sku_name,image,price")
                        .eq("order_id", id));
                List<OrderVo.OrderItemVo> orderItemVos = BeanUtil.copyList(orderItems, OrderVo.OrderItemVo.class);
                i.setOrderItemVos(orderItemVos);
            });
        }
        return orderVos;
    }

    @Override
    public List<OrderVo> findUserRefund(Integer userId, Page<XwOrder> page) {
        QueryWrapper<XwOrder> wrapper = new QueryWrapper<>();
        wrapper.select("id,order_no,actual_amount,`status`");
        wrapper.eq("`status`", OrderStatus.AFTER_SALE.getCode());
        wrapper.eq("user_id", userId)
                .eq("user_delete_flag", 0);
        wrapper.orderByDesc("update_time");
        page(page, wrapper);
        List<OrderVo> orderVos = BeanUtil.copyList(page.getRecords(), OrderVo.class);
        if (orderVos != null) {
            orderVos.forEach(i -> {
                Integer id = i.getId();
                List<XwOrderItem> orderItems = orderItemService.list(new QueryWrapper<XwOrderItem>()
                        .select("id,product_name,`count`,sku_name,image,price")
                        .eq("order_id", id));
                List<OrderVo.OrderItemVo> orderItemVos = BeanUtil.copyList(orderItems, OrderVo.OrderItemVo.class);
                XwOrderRefund orderRefund = orderRefundService.getOne(new QueryWrapper<XwOrderRefund>()
                        .select("id,`status`")
                        .eq("order_id", i.getId()));
                i.setRefundStatus(orderRefund.getStatus());
                i.setOrderItemVos(orderItemVos);
            });
        }
        return orderVos;
    }

    @Override
    public OrderDetailVo detail(Integer orderId) {
        XwOrder order = baseMapper.selectOne(new QueryWrapper<XwOrder>()
                .eq("id", orderId)
                .eq("user_delete_flag", 0));
        if (order == null) {
            throw new XwException("订单不存在");
        }
        OrderDetailVo orderDetailVo = new OrderDetailVo();
        //未付款的订单自动关闭的时间
        if (Arrays.asList(OrderStatus.PAY_NO.getCode(), OrderStatus.NO.getCode()).contains(order.getStatus())) {
            LocalDateTime createTime = order.getCreateTime();
            LocalDateTime now = LocalDateTime.now();
            LocalDateTime time = now.minusMinutes(30);
            Duration between = Duration.between(time, createTime);
            long seconds = between.getSeconds();
            if (seconds < 0) {
                seconds = 0;
            }
            orderDetailVo.setSecond(seconds);
        }
        //发货的最新的一条快递信息
        if (!Arrays.asList(OrderStatus.PAY_NO.getCode(),
                OrderStatus.PAY_SUCCESS.getCode(),
                OrderStatus.CLOSE.getCode(),
                OrderStatus.AFTER_SALE.getCode(),
                OrderStatus.NO.getCode()).contains(order.getStatus())) {
            CourierInfo courierInfo = orderCourierService.queryCourier(orderId);
            if (courierInfo.getInfos() == null || courierInfo.getInfos().size() == 0) {
                CourierInfo.Info info = new CourierInfo.Info();
                LocalDateTime sendTime = order.getSendTime();
                info.setTime(sendTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                info.setMessage("您的订单已出库");
                orderDetailVo.setCourierInfo(info);
            } else {
                orderDetailVo.setCourierInfo(courierInfo.getInfos().get(0));
            }
        }
        BeanUtils.copyProperties(order, orderDetailVo);
        Integer id = order.getId();
        List<XwOrderItem> orderItems = orderItemService.list(new QueryWrapper<XwOrderItem>()
                .select("id,product_name,`count`,sku_name,image,price")
                .eq("order_id", id));
        List<OrderDetailVo.OrderItem> orderItemVos = BeanUtil.copyList(orderItems, OrderDetailVo.OrderItem.class);
        orderDetailVo.setOrderItems(orderItemVos);
        //售后
        XwOrderRefund orderRefund = orderRefundService.getBaseMapper().selectOne(
                new QueryWrapper<XwOrderRefund>()
                        .select("`status`").eq("order_id", id));
        if (order.getStatus() == 5) {
            if (orderRefund != null) {
                orderDetailVo.setRefundStatus(orderRefund.getStatus());
            }
        } else {
            if (Arrays.asList(OrderStatus.PAY_SUCCESS.getCode(),
                    OrderStatus.SEND.getCode(),
                    OrderStatus.RECEIVE.getCode()).contains(order.getStatus())) {
                orderDetailVo.setRefundButton(orderRefund == null ? 0 : 1);
            } else {
                orderDetailVo.setRefundButton(1);
            }
        }
        return orderDetailVo;
    }

    @Override
    @Transactional
    public void receive(Integer orderId, Integer userId) {
        XwOrder order = baseMapper.selectOne(new QueryWrapper<XwOrder>()
                .select("id,actual_amount")
                .eq("id", orderId)
                .eq("user_delete_flag", 0)
                .eq("`status`", OrderStatus.SEND.getCode())
        );
        if (order == null) {
            throw new XwException("订单不存在");
        }
        order.setStatus(OrderStatus.RECEIVE.getCode());
        order.setReceiveTime(LocalDateTime.now());
        updateById(order);
        XwUser user = userService.getOne(new QueryWrapper<XwUser>().select("id,integral").eq("id", userId));
        int integral = user.getIntegral() + order.getActualAmount().intValue();
        user.setIntegral(integral);
        userService.updateById(user);
        XwIntegralRecord record = new XwIntegralRecord();
        record.setCreateTime(LocalDateTime.now());
        record.setType(0);
        record.setMessage("购买商品获取积分");
        record.setUserId(userId);
        record.setNum(order.getActualAmount().intValue());
        record.setSourceId(orderId);
        integralRecordService.save(record);
    }

    @Override
    @Transactional
    public void comment(List<Comment.CommentItem> items, Integer orderId, Integer userId) {
        XwOrder order = getOne(new QueryWrapper<XwOrder>().select("id")
                .eq("id", orderId)
                .eq("`status`", OrderStatus.RECEIVE.getCode()));

        if (order == null) {
            throw new XwException("该订单不存在");
        }
        order.setStatus(OrderStatus.SUCCESS.getCode());
        order.setUpdateTime(LocalDateTime.now());
        order.setSuccessTime(LocalDateTime.now());
        updateById(order);

        XwUser user = userService.getById(userId);
        items.forEach(s -> {
            XwOrderItem orderItem = orderItemService.getById(s.getOrderItemId());
            XwOrderComment orderComment = new XwOrderComment();
            orderComment.setComment(s.getContent());
            orderComment.setCreateTime(LocalDateTime.now());
            orderComment.setImage(s.getImage());
            orderComment.setLevel(s.getLevel());
            orderComment.setOrderId(order.getId());
            orderComment.setOrderItemId(s.getOrderItemId());
            orderComment.setProductId(orderItem.getProductId());
            orderComment.setSkuName(orderItem.getSkuName());
            orderComment.setUserAvatar(user.getAvatarUrl());
            orderComment.setUserId(userId);
            orderComment.setUserNickname(user.getNickname());
            orderCommentService.save(orderComment);
        });


    }

    @Override
    @Transactional
    public void applyRefund(Integer orderId, String reason) {
        XwOrder order = baseMapper.selectOne(new QueryWrapper<XwOrder>()
                .select("id,actual_amount,`status`").eq("id", orderId)
                .in("`status`", OrderStatus.PAY_SUCCESS.getCode(), OrderStatus.RECEIVE.getCode(), OrderStatus.SEND.getCode())
                .eq("user_delete_flag", 0));

        if (order == null) {
            throw new XwException("该订单不存在");
        }
        XwOrderRefund orderRefund = orderRefundService.getBaseMapper().selectOne(new QueryWrapper<XwOrderRefund>()
                .select("id")
                .eq("order_id", orderId));

        if (orderRefund != null) {
            throw new XwException("该订单不能再次退款");
        }
        //修改订单状态
        Integer status = order.getStatus();
        order.setStatus(OrderStatus.AFTER_SALE.getCode());
        order.setUpdateTime(LocalDateTime.now());
        updateById(order);
        //保存退款
        orderRefund = new XwOrderRefund();
        orderRefund.setStatus(RefundStatus.APPLAYING.getCode());
        orderRefund.setCreateTime(LocalDateTime.now());
        orderRefund.setOrderBeforeStatus(status);
        orderRefund.setRefundNo(GenerateOrderNO.makeOrderNum());
        orderRefund.setOrderId(orderId);
        orderRefund.setRefundAmount(order.getActualAmount());
        orderRefundService.save(orderRefund);

        //退款记录表

        orderRefundRecordService.save(orderRefund.getId(), RefundConstant.APPLAY);

    }

    @Override
    public RefundDetail findRefundDetail(Integer id) {
        XwOrderRefund orderRefund = orderRefundService.getOne(new QueryWrapper<XwOrderRefund>()
                .eq("order_id", id));

        if (orderRefund == null) {
            throw new XwException("数据不存在");
        }
        RefundDetail refundDetail = new RefundDetail();

        refundDetail.setAmount(orderRefund.getRefundAmount());
        refundDetail.setRefundNo(orderRefund.getRefundNo());
        refundDetail.setStatus(orderRefund.getStatus());
        refundDetail.setTime(orderRefund.getCreateTime());
        refundDetail.setReason(orderRefund.getReason());
        List<XwOrderRefundRecord> refundRecords = orderRefundRecordService.list(new QueryWrapper<XwOrderRefundRecord>()
                .eq("order_refund_id", orderRefund.getId())
                .orderByDesc("create_time"));
        List<RefundDetail.Record> records = Lists.newArrayListWithCapacity(refundRecords.size());
        refundRecords.forEach(s -> {
            RefundDetail.Record record = new RefundDetail.Record();
            record.setId(s.getId());
            record.setMessage(s.getMessage());
            record.setTime(s.getCreateTime());
            record.setReason(s.getReason());
            records.add(record);
        });
        refundDetail.setRecords(records);
        List<XwOrderItem> orderItems = orderItemService.list(new QueryWrapper<XwOrderItem>()
                .eq("order_id", id));
        List<RefundDetail.Product> products = BeanUtil.copyList(orderItems, RefundDetail.Product.class);
        refundDetail.setProducts(products);
        return refundDetail;
    }

    @Override
    public void continueRefund(Integer orderId) {

        XwOrderRefund orderRefund = orderRefundService.getBaseMapper().selectOne(new QueryWrapper<XwOrderRefund>()
                .select("id")
                .eq("`status`", RefundStatus.REJECT.getCode())
                .eq("order_id", orderId));

        if (orderRefund == null) {
            throw new XwException("退款数据不存在");
        }
        //修改退款状态
        orderRefund.setStatus(RefundStatus.APPLAYING.getCode());
        orderRefundService.updateById(orderRefund);

        //退款记录表
        orderRefundRecordService.save(orderRefund.getId(), RefundConstant.CONTINUE_APPLAY);
    }

    @Override
    @Transactional
    public void goOnOrder(Integer orderId) {
        XwOrder order = getOne(new QueryWrapper<XwOrder>()
                .select("id").eq("id", orderId)
                .eq("`status`", OrderStatus.AFTER_SALE.getCode())
                .eq("user_delete_flag", 0));

        if (order == null) {
            throw new XwException("该订单不存在");
        }

        XwOrderRefund orderRefund = orderRefundService.getOne(new QueryWrapper<XwOrderRefund>()
                .select("id,order_before_status")
                .eq("order_id", orderId)
                .eq("`status`", RefundStatus.REJECT.getCode()));
        if (orderRefund == null) {
            throw new XwException("数据异常");
        }
        //修改订单状态
        order.setStatus(orderRefund.getOrderBeforeStatus());
        updateById(order);

        //修改退款表的状态
        orderRefund.setStatus(RefundStatus.GO_ON_ORDER.getCode());
        orderRefundService.updateById(orderRefund);

        //保存退款记录
        orderRefundRecordService.save(orderRefund.getId(), RefundConstant.GOON);
    }


    @Override
    public Page<OrderListVo> businessOrderList(Integer type, String orderNo, String nickname,
                                               String receiveName, String receivePhone, LocalDate startTime,
                                               LocalDate endTime, Page<OrderDo> page) {

        baseMapper.findBusinessOrder(page, type,
                orderNo, nickname, receiveName, receivePhone, startTime, endTime);
        List<OrderListVo> orderListVos = BeanUtil.copyList(page.getRecords(), OrderListVo.class);
        orderListVos.forEach(i -> {
            Integer id = i.getId();
            i.setProductName(getProductName(id));
        });
        Page<OrderListVo> pageVo = new Page<>(page.getCurrent(), page.getSize());
        pageVo.setRecords(orderListVos);
        pageVo.setTotal(page.getTotal());
        pageVo.setPages(page.getPages());
        return pageVo;
    }

    @Override
    public Page<OrderListVo> refundOrderList(Integer refundType, String orderNo, String nickname,
                                             String receiveName, String receivePhone,
                                             LocalDate startTime, LocalDate endTime, Page<OrderDo> page) {
        baseMapper.findRefundOrder(page, refundType,
                orderNo, nickname, receiveName, receivePhone, startTime, endTime);
        List<OrderListVo> orderListVos = BeanUtil.copyList(page.getRecords(), OrderListVo.class);
        orderListVos.forEach(i -> {
            Integer id = i.getId();
            i.setProductName(getProductName(id));
        });
        Page<OrderListVo> pageVo = new Page<>(page.getCurrent(), page.getSize());
        pageVo.setRecords(orderListVos);
        pageVo.setTotal(page.getTotal());
        pageVo.setPages(page.getPages());
        return pageVo;
    }

    private String getProductName(Integer orderId) {
        List<XwOrderItem> orderItems = orderItemService.list(new QueryWrapper<XwOrderItem>()
                .select("id,product_name,`count`").eq("order_id", orderId));
        int sum = orderItems.stream().mapToInt(XwOrderItem::getCount).sum();
        return orderItems.get(0).getProductName().substring(0, 10) + "...等" + sum + "件商品";
    }

    @Override
    @Transactional
    public void send(Integer orderId, Integer companyId, String courierNo) {
        //修改订单状态
        XwOrder order = baseMapper.selectOne(new QueryWrapper<XwOrder>()
                .select("id").eq("id", orderId)
                .eq("`status`", OrderStatus.PAY_SUCCESS.getCode())
                .eq("user_delete_flag", 0));

        if (order == null) {
            throw new XwException("该订单不存在");
        }

        order.setStatus(OrderStatus.SEND.getCode());
        order.setSendTime(LocalDateTime.now());
        updateById(order);
        XwCourierCompany courierCompany = courierCompanyService.getById(companyId);
        //创建物流
        XwOrderCourier orderCourier = new XwOrderCourier();
        orderCourier.setOrderId(orderId);
        orderCourier.setCourierCode(courierCompany.getCode());
        orderCourier.setCourierName(courierCompany.getName());
        orderCourier.setCourierNo(courierNo);
        orderCourier.setCreateTime(LocalDateTime.now());
        orderCourier.setUpdateTime(LocalDateTime.now());
        orderCourierService.save(orderCourier);

    }

    @Override
    @Transactional
    public void handleReject(Integer orderId, String reason) {

        XwOrderRefund orderRefund = orderRefundService.getBaseMapper().selectOne(new QueryWrapper<XwOrderRefund>()
                .select("id")
                .eq("order_id", orderId)
                .eq("`status`", RefundStatus.APPLAYING.getCode()));

        if (orderRefund == null) {
            throw new XwException("退款数据不存在");
        }
        //修改退款状态
        orderRefund.setStatus(RefundStatus.REJECT.getCode());
        orderRefundService.updateById(orderRefund);
        //保存退款记录
        orderRefundRecordService.save(orderRefund.getId(), RefundConstant.REJECT, reason);

    }

    @Override
    @Transactional
    public void handleAgree(Integer orderId) {

        XwOrderRefund orderRefund = orderRefundService.getBaseMapper().selectOne(new QueryWrapper<XwOrderRefund>()
                .select("id")
                .eq("order_id", orderId)
                .eq("`status`", RefundStatus.APPLAYING.getCode()));

        if (orderRefund == null) {
            throw new XwException("退款数据不存在");
        }
        //修改退款状态
        orderRefund.setStatus(RefundStatus.AGREE.getCode());
        orderRefundService.updateById(orderRefund);

        //保存退款记录
        orderRefundRecordService.save(orderRefund.getId(), RefundConstant.ARGEE);
    }

    @Override
    public CourierInfoVo findCourierInfo(Integer orderId) {

        XwOrder order = getOne(new QueryWrapper<XwOrder>()
                .select("id,province,city,send_time")
                .eq("id", orderId));

        if (order == null) {
            throw new XwException("订单不存在");
        }

        XwOrderCourier orderCourier = orderCourierService
                .getOne(new QueryWrapper<XwOrderCourier>()
                        .eq("order_id", orderId));

        if (orderCourier == null) {
            throw new XwException("数据不存在");
        }

        CourierInfo courierInfo = orderCourierService.queryCourier(orderId);
        CourierInfoVo courierInfoVo = new CourierInfoVo();
        courierInfoVo.setSendAddress("浙江/杭州");
        courierInfoVo.setReceiveAddress(order.getProvince() + "/" + order.getCity());
        courierInfoVo.setCourierName(orderCourier.getCourierName());
        courierInfoVo.setCourierNo(orderCourier.getCourierNo());
        if (courierInfo.getInfos() == null || courierInfo.getInfos().size() == 0) {
            CourierInfo.Info info = new CourierInfo.Info();
            LocalDateTime sendTime = order.getSendTime();
            info.setTime(sendTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            info.setMessage("您的订单已出库");
            ArrayList<CourierInfo.Info> infos = Lists.newArrayListWithCapacity(1);
            infos.add(info);
            courierInfoVo.setInfos(infos);
            courierInfoVo.setStatus(CourierStatus.PACKAGE.getCode());
        } else {
            courierInfoVo.setInfos(courierInfo.getInfos());
            courierInfoVo.setStatus(courierInfo.getStatus());
        }


        List<XwOrderItem> orderItems = orderItemService.list(new QueryWrapper<XwOrderItem>()
                .select("id,image")
                .eq("order_id", orderId));
        List<String> collect = orderItems.stream()
                .map(XwOrderItem::getImage)
                .collect(Collectors.toList());
        courierInfoVo.setImages(collect);
        return courierInfoVo;
    }


    @Override
    public OrderCountVo findOrderCount(Integer userId) {

        OrderCountVo orderCountVo = new OrderCountVo();
        int count1 = count(new QueryWrapper<XwOrder>()
                .eq("user_id", userId)
                .in("`status`", OrderStatus.PAY_NO.getCode(), OrderStatus.NO.getCode()));

        orderCountVo.setNoPayCount(count1);

        int count2 = count(new QueryWrapper<XwOrder>()
                .eq("user_id", userId)
                .eq("`status`", OrderStatus.PAY_SUCCESS.getCode()));

        orderCountVo.setNoSendCount(count2);

        int count3 = count(new QueryWrapper<XwOrder>()
                .eq("user_id", userId)
                .eq("`status`", OrderStatus.SEND.getCode()));

        orderCountVo.setNoReceiveCount(count3);

        int count4 = count(new QueryWrapper<XwOrder>()
                .eq("user_id", userId)
                .eq("`status`", OrderStatus.RECEIVE.getCode()));

        orderCountVo.setNoCommentCount(count4);

        int count5 = orderRefundService.selectShowCount(userId);

        orderCountVo.setAfterSaleCount(count5);
        return orderCountVo;
    }

    @Override
    public OrderCommentVo findOrderComment(Integer id) {
        List<XwOrderItem> orderItems = orderItemService.list(new QueryWrapper<XwOrderItem>()
                .select("id,product_name,sku_name,image")
                .eq("order_id", id));
        List<OrderCommentVo.Item> items = BeanUtil.copyList(orderItems, OrderCommentVo.Item.class);
        OrderCommentVo orderCommentVo = new OrderCommentVo();
        orderCommentVo.setId(id);
        orderCommentVo.setItems(items);
        return orderCommentVo;
    }
}
